#include "EpilWhileStatementInterpreter.h"
#include "EpilInterpreterException.h"
#include "EpilInterpreter.h"
#include "EpilExpressionInterpreter.h"
#include "EpilChunkInterpreter.h"
#include "EpilObjectHelper.h"


EpilWhileStatementInterpreter::EpilWhileStatementInterpreter( EpilInterpreter * interpreter )
: EpilInterpreterBase( interpreter )
, m_exitReason( ECER_Normal )
, m_exitLocation( EpilLexLocation::InvalidLocation )
{
}


void EpilWhileStatementInterpreter::Run( const EpilWhileStatementCode * code )
{
	const EpilExpressionCodeBase * conditionCode = code->GetCondition();
	
	for(;;)
	{
		EpilExpressionInterpreter ei( this->GetInterpreter() );
		ei.Run( conditionCode );
		EpilObject * condition = ei.GetObject();

		bool result = EpilObjectHelper::IsConditionTrue( condition );
		condition->ReleaseCopy();

		if( result == false )
		{
			break;
		}

		EpilChunkCode * chunk = code->GetBlock();
		EpilChunkInterpreter ci( this->GetInterpreter() );
		this->GetInterpreter()->EnterScope();
		try
		{
			ci.Run( chunk );
		}
		catch( ... )
		{
			this->GetInterpreter()->LeaveScope();
			throw;
		}
		EpilChunkExitReason reason = ci.GetExitReason();
		if( reason == ECER_Break )
		{
			break;
		}
		if( reason == ECER_Continue )
		{
			continue;
		}
		if( reason == ECER_Return )
		{
			m_exitReason = ECER_Return;
			m_exitLocation = ci.GetExitLocation();
			break;
		}
	}
}